package Shaders 
{
	import com.junkbyte.console.Cc;
	import flash.events.ProgressEvent;
	
	import flash.display.Shader;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.events.SecurityErrorEvent;
	import flash.net.URLLoader;
	import flash.net.URLLoaderDataFormat;
	import flash.net.URLRequest;
	
	public class ShadersManager
	{
		private static var FShaders:Vector.<UserShader>;
		private static var FLoader:URLLoader;
		private static var FDispatcher:EventDispatcher;
		
		public function ShadersManager() 
		{}
		
		public static function Load(AURL:String):void
		{
			if (!FShaders)
				FShaders = new Vector.<UserShader>;
			
			if (FLoader)
			{
				FLoader.removeEventListener(ProgressEvent.PROGRESS, OnProgress);
				FLoader.removeEventListener(Event.COMPLETE, OnShaderLoaded);
				FLoader.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, OnSecurityError);
				FLoader.removeEventListener(IOErrorEvent.IO_ERROR, OnIOError);
			}
			
			FLoader = new URLLoader();
			FLoader.dataFormat = URLLoaderDataFormat.BINARY;
			FLoader.addEventListener(ProgressEvent.PROGRESS, OnProgress);
			FLoader.addEventListener(Event.COMPLETE, OnShaderLoaded);
			FLoader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, OnSecurityError);
			FLoader.addEventListener(IOErrorEvent.IO_ERROR, OnIOError);
			FLoader.load(new URLRequest(AURL));
		}
			
		public static function addEventListener(type:String, listener:Function):void
		{
			Dispatcher.addEventListener(type, listener);
		}
		
		static private function OnProgress(e:ProgressEvent):void 
		{
			Cc.logch('ShaderManager', 'Shader loaded at ' + Math.round(e.bytesLoaded / e.bytesTotal) * 100 + '%');
		}
		
		private static function OnShaderLoaded(e:Event):void 
		{			
			var vShader:UserShader = new UserShader(e.target.data);
			FShaders.push(vShader);
			var vS:String = 'Inputs: ' + vShader.Inputs.length + ', ' +
							'Parameters: ' + vShader.Parameters.length;
			Cc.logch('ShaderManager', 'Shader "'  + vShader.Name + '" has been loaded. ' + vS);
			Dispatcher.dispatchEvent(new ShaderManagerEvent(ShaderManagerEvent.COMPLETE, vShader));
			FLoader.removeEventListener(Event.COMPLETE, OnShaderLoaded);
			FLoader.removeEventListener(ProgressEvent.PROGRESS, OnProgress);
		}
		
		private static function OnSecurityError(e:SecurityErrorEvent):void 
		{			
			Cc.errorch('ShaderManager', e.text);			
			FLoader.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, OnSecurityError);
		}
		
		private static function OnIOError(e:IOErrorEvent):void 
		{			
			Cc.errorch('ShaderManager', e.text);			
			FLoader.removeEventListener(IOErrorEvent.IO_ERROR, OnIOError);
		}
		
		private static function get Dispatcher():EventDispatcher
		{
			if (!FDispatcher)
				FDispatcher = new EventDispatcher();
			return FDispatcher;
		}
		
		public static function SahderAt(AIndex:int):UserShader		
		{
			return FShaders[AIndex];
		}
	}
}